// 记录 Promise 的三种状态
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

/**
 * 运行一个微队列任务
 * 把传递的函数放到微队列中
 * @param {Function} callback
 */
function runMicroTask(callback) {
    // 决断 node 环境
    if (process && process.nextTick) {
        process.nextTick(callback)
    } else if (MutationObserver) {
        const observer = new MutationObserver(callback)
    } else {
        setTimeout(callback, 0)
    }
}

/**
 * 手写 Promise
 */
class MyPromise {

    /**
     * MyPromise 构造器
     * @param {Function} executor
     */
    constructor(executor) {
        this._state = PENDING // 初始状态
        this._data = undefined  //数据
        this._handlers = [] // 处理函数队列

        try {
            executor(this._resolve.bind(this), this._reject.bind(this))
        } catch (error) {
            this._reject(error)
        }
    }

    /**
     * 向处理队列中添加一个函数
     * @param {Function} executor
     * @param {String} state
     * @param {Function} resove
     * @param {Function} reject
     */
    _pushHandler(executor, state, resove, reject) {
        this._handlers.push({executor, state, resove, reject})
    }


    /**
     * 处理一个 Handler
     * @param handler
     * @private
     */
    _runOneHandler(handler) {
        if (this._state === handler.state) {
            runMicroTask(handler.executor)
        }
    }

    /**
     * 根据实际情况,执行处理函数队列
     * @private
     */
    _runHandlers() {
        if (this._state === PENDING) return

        while (this._handlers[0]){
            const handler = this._handlers[0]
            this._runOneHandler(handler)
            this._handlers.shift()
        }
    }

    /**
     * Promise A+ 规范的 then 方法
     * @param {Function} onFulfilled
     * @param {Function} onRejected
     * @returns {MyPromise}
     */
    then(onFulfilled, onRejected) {
        return new MyPromise((resolve, reject) => {
            this._pushHandler(onFulfilled, FULFILLED, resolve, reject)
            this._pushHandler(onRejected, REJECTED, resolve, reject)
            this._runHandlers()
        })
    }

    /**
     * 设置 Mypromise 的状态和数据
     * @param {String} state MyPromise 状态
     * @param {any} data
     * @private
     */
    _setState(state, data) {
        if (this._state !== PENDING) return
        this._state = state
        this._data = data
    }

    /**
     * 切换状态为 fulfilled
     * @private
     */
    _resolve(data) {
        this._setState(FULFILLED, data)
    }

    /**
     * 切换状为 reject
     * @param {any} reason
     * @private
     */
    _reject(reason) {
        this._setState(REJECTED, reason)
    }

}

const pro = new MyPromise((resolve, reject) => {
    setTimeout(() => {
        resolve(1)
        // reject(2)
    }, 1000)
})

setTimeout(console.log, 1000, pro)

const pro2 = pro.then(
    (value) => {
        console.log(value)
        console.log(pro)
    },
    (reason) => {
        console.log(reason)
    })